#ifndef LIB_SYSCALL_H
#define LIB_SYSCALL_H 

#include "utility/Types.h"
#include "Const.h"
#include "Irq.h"

void HandleSyscallException();

//void SyscallExceptionHandler(ExceptionFrameType* frame);

typedef struct SyscallArgs
{
    int id;
    int arg0;
    int arg1;
    int arg2;
    int arg3;
} SyscallArgsType;

static inline int Syscall(SyscallArgsType* args)
{
    const unsigned long sys_gate_addr[] = {0, GDT_SYSCALL_SELECTOR | 0};
    int ret;
    // lcalll 执行之后，EAX（即 ret 变量）中保存的是内核系统调用处理函数的返回值。
    __asm__ __volatile__(
        "push %[arg3]\n\t"
        "push %[arg2]\n\t"
        "push %[arg1]\n\t"
        "push %[arg0]\n\t"
        "push %[id]\n\t"
        "lcalll *(%[gate])\n\n"
        :"=a"(ret)
        :[arg3]"r"(args->arg3), [arg2]"r"(args->arg2), [arg1]"r"(args->arg1),
        [arg0]"r"(args->arg0), [id]"r"(args->id),
        [gate]"r"(sys_gate_addr));
    return ret;
}

static inline int MSleep(uint32_t ms)
{
    if (ms<=0)
    {
        return 0;
    }

    SyscallArgsType args;
    args.id = SYS_SLEEP;
    args.arg0 = ms;
    return Syscall(&args);
}

static inline int GetProcessId()
{
    SyscallArgsType args;
    args.id = SYS_GET_PID;
    return Syscall(&args);
}

static inline int PrintMsg(char* fmt, int arg)
{
    SyscallArgsType args;
    args.id = SYS_PRINT_MSG;
    args.arg0 = (int)fmt;
    args.arg1 = arg;
    return Syscall(&args);
}

static inline int Fork()
{
    SyscallArgsType args;
    args.id = SYS_FORK;
    return Syscall(&args);
}

// 等价于 
static inline int Execve(const char* name, char* const argv[], char* const env[])
{
    SyscallArgsType args;
    args.id = SYS_EXECVE;
    args.arg0 = (int)name;
    args.arg1 = (int)argv;
    args.arg2 = (int)env;
    return Syscall(&args);
}

static inline int Yield(void)
{
    SyscallArgsType args;
    args.id = SYS_YIELD;
    return Syscall(&args);
}

#endif